home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / wgt / wgt_cd / cdrom.c < prev    next >
C/C++ Source or Header  |  1994-07-20  |  20KB  |  782 lines

  1. /*                          CDROM AUDIO ROUTINES
  2.                   By Barry Egerter
  3.  
  4.                 Written July 18, 1994
  5.  
  6.                 Using Borland C++ 3.1
  7.  
  8.            Code : FREEWARE - alter and use at will.
  9.  
  10.  
  11.         Internet Email:      barry.egerter@softnet.com
  12. */
  13. #include <dos.h>
  14. #include <io.h>
  15. #include <mem.h>
  16. #include <fcntl.h>
  17.  
  18. #define CDROM 0x21
  19. #define EJECT_TRAY 0
  20. #define RESET 2
  21. #define CLOSE_TRAY 5
  22. #define MEDIA_CHANGE 9
  23. #define BUSY  512
  24. #define TRACK_MASK 208
  25.  
  26. typedef struct playinfo {
  27.   unsigned char control;
  28.   unsigned char adr;
  29.   unsigned char track;
  30.   unsigned char index;
  31.   unsigned char min;
  32.   unsigned char sec;
  33.   unsigned char frame;
  34.   unsigned char zero;
  35.   unsigned char amin;
  36.   unsigned char asec;
  37.   unsigned char aframe;
  38. };
  39.  
  40.  
  41. typedef struct volumeinfo {
  42.     unsigned char mode;
  43.     unsigned char input0;
  44.     unsigned char volume0;
  45.     unsigned char input1;
  46.     unsigned char volume1;
  47.     unsigned char input2;
  48.     unsigned char volume2;
  49.     unsigned char input3;
  50.     unsigned char volume3;
  51. };
  52.  
  53.  
  54. struct {
  55.   unsigned short drives;
  56.   unsigned char  first_drive;
  57.   unsigned short current_track;
  58.   unsigned long  track_position;
  59.   unsigned char  track_type;
  60.   unsigned char  low_audio;
  61.   unsigned char  high_audio;
  62.   unsigned char  disk_length_min;
  63.   unsigned char  disk_length_sec;
  64.   unsigned char  disk_length_frames;
  65.   unsigned long     endofdisk;
  66.   unsigned char  upc[7];
  67.   unsigned char  diskid[6];
  68.   unsigned long  status;
  69.   unsigned short error;      /* See description below */
  70. } cdrom_data;
  71.  
  72. /* CDROM_DATA.ERROR Description
  73.  
  74.   Bit 15         - Error bit
  75.   Bit 14-10      - Reserved
  76.   Bit  9         - Busy
  77.   Bit  8         - Done
  78.   Bit  7-0       - Error code (bit 15 on)
  79.  
  80. Error codes are the following:
  81.  
  82.   0  Write-protect violation
  83.   1  Unknown unit
  84.   2  Drive not ready
  85.   3  Unknown command
  86.   4  CRC error
  87.   5  Bad drive request structure length
  88.   6  Seek error
  89.   7  Unknown media
  90.   8  Sector not found
  91.   9  Printer out of paper
  92.   A  Write fault
  93.   B  Read fault
  94.   C  General failure
  95.   D  Reserved
  96.   E  Reserved
  97.   F  Invalid disk change
  98. */
  99.  
  100.  
  101. /*   Multiplex Interrupt routines
  102.      "borrowed" from Ralf Brown's MSDOS Interrupt List v4.1
  103.  
  104. INT 21 - CD-ROM device driver - IOCTL INPUT
  105.     AX = 4402h
  106.     BX = file handle referencing character device for CD-ROM driver
  107.     CX = number of bytes to read
  108.     DS:DX -> control block (see #0563)
  109. Return: CF clear if successful
  110.         AX = number of bytes actually read
  111.     CF set on error
  112.         AX = error code (01h,05h,06h,0Dh) (see #0770 at AH=59h)
  113. Note:    the data returned depends on the first byte of the control block; the
  114.       remainder of the control block is filled by the driver
  115. SeeAlso: AX=4403h"CD-ROM",INT 2F/AX=0802h
  116.  
  117. (Table 0562)
  118. Values for CD-ROM data being requested:
  119.  00h    device driver header address
  120.  01h    drive head location
  121.  02h    reserved
  122.  03h    error statistics
  123.  04h    audio channel info
  124.  05h    raw drive bytes (uninterpreted and device-specific)
  125.  06h    device status
  126.  07h    sector size
  127.  08h    volume size
  128.  09h    media change status
  129.  0Ah    audio disk info
  130.  0Bh    audio track info
  131.  0Ch    audio Q-Channel info
  132.  0Dh    audio sub-channel info
  133.  0Eh    UPC code
  134.  
  135. Format of CD-ROM control block:
  136. Offset    Size    Description    (Table 0563)
  137.  00h    BYTE    data being requested (see #0562)
  138. ---function 00h---
  139.  01h    DWORD    device driver header address (see also AH=52h)
  140. ---function 01h---
  141.  01h    BYTE    addressing mode
  142.         00h HSG
  143.         01h Red Book
  144.  02h    DWORD    current location of drive's head
  145.         logical sector number in HSG mode
  146.         frame/second/minute/unused in Red Book mode
  147.         (HSG sector = minute * 4500 + second * 75 + frame - 150)
  148. ---function 03h---
  149.  01h  N BYTEs    undefined as of 5 Aug 88 specification
  150. ---function 04h---
  151.  01h    BYTE    input channel (0-3) for output channel 0
  152.  02h    BYTE    volume for output channel 0
  153.  03h    BYTE    input channel (0-3) for output channel 1
  154.  04h    BYTE    volume for output channel 1
  155.  05h    BYTE    input channel (0-3) for output channel 2
  156.  06h    BYTE    volume for output channel 2
  157.  07h    BYTE    input channel (0-3) for output channel 3
  158.  08h    BYTE    volume for output channel 3
  159. Notes:    output channels 0 and 1 are left and right, 2 and 3 are left prime and
  160.       right prime; a volume of 00h is off
  161.     the default setting is for each input channel to be assigned to the
  162.       same-numbered output channel at full (FFh) volume
  163. ---function 05h---
  164.  01h    BYTE    number of bytes read
  165.  02h 128 BYTEs    buffer for drive bytes
  166. ---function 06h---
  167.  01h    DWORD    device parameters (see #0564)
  168. ---function 07h---
  169.  01h    BYTE    read mode
  170.         00h cooked
  171.         01h raw
  172.  02h    WORD    sector size in bytes
  173. ---function 08h---
  174.  01h    DWORD    volume size in sectors
  175. ---function 09h---
  176.  01h    BYTE    media change status
  177.         00h don't know
  178.         01h media unchanged
  179.         FFh media has been changed
  180. ---function 0Ah---
  181.  01h    BYTE    lowest audio track number
  182.  02h    BYTE    highest audio track number
  183.  03h    DWORD    start address of lead-out track (Red Book format)
  184. --function 0Bh---
  185.  01h    BYTE    track number (set by caller)
  186.  02h    DWORD    starting point of track (Red Book format)
  187.  06h    BYTE    track control info
  188.         bits 15,14,12: track type (notice: bits not contiguous!)
  189.             000 two audio channels, no pre-emphasis
  190.             001 two audio channels with pre-emphasis
  191.             010 data track
  192.             100 four audio channels, no pre-emphasis
  193.             101 four audio channels with pre-emphasis
  194.             other reserved
  195.         bit 13: digital copy permitted
  196. ---function 0Ch---
  197.  01h    BYTE    CONTROL and ADR byte (as received from drive)
  198.  02h    BYTE    track number
  199.  03h    BYTE    point or index
  200.  04h    BYTE    minute    \
  201.  05h    BYTE    second     > running time within track
  202.  06h    BYTE    frame    /
  203.  07h    BYTE    zero
  204.  08h    BYTE    "AMIN" or "PMIN"     \
  205.  09h    BYTE    "ASEC" or "PSEC"      > running time on disk
  206.  0Ah    BYTE    "AFRAME" or "PFRAME" /
  207. ---function 0Dh---
  208.  01h    DWORD    starting frame address (Red Book format)
  209.  05h    DWORD    transfer address
  210.  09h    DWORD    number of sectors to read
  211. Note:    copies 96 bytes of sub-channel info per sector into buffer
  212. ---function 0Eh---
  213.  01h    BYTE    CONTROL and ADR byte
  214.  02h  7 BYTEs    UPC/EAN code (13 BCD digits,low-order nybble of last byte is 0)
  215.  09h    BYTE    zero
  216.  0Ah    BYTE    "AFRAME"
  217.  
  218. Bitfields for CD-ROM device parameters:
  219. Bit(s)    Description    (Table 0564)
  220.  0    door open
  221.  1    door unlocked
  222.  2    supports raw reading in addition to cooked
  223.  3    writable
  224.  4    can play audio/video tracks
  225.  5    supports interleaving
  226.  6    reserved
  227.  7    supports prefetch requests
  228.  8    supports audio channel control
  229.  9    supports Red Book addressing in addition to HSG
  230.  10    audio is playing
  231. */
  232.  
  233. static union REGS inregs, outregs;
  234. static struct SREGS sregs;
  235.  
  236.  
  237. void device_request (void *block)
  238. {
  239.   inregs.x.ax = 0x1510;
  240.   inregs.x.cx = cdrom_data.first_drive;
  241.   inregs.x.bx = FP_OFF (block);
  242.   sregs.es = FP_SEG (block);
  243.   int86x (0x2f, &inregs, &outregs, &sregs);
  244. }
  245.  
  246.  
  247. void red_book (unsigned long value, unsigned char *min, unsigned char *sec, unsigned char *frame)
  248. {
  249.   *frame = value & 0x000000ff;
  250.   *sec = (value & 0x0000ff00) >> 8;
  251.   *min = (value & 0x00ff0000) >> 16;
  252. }
  253.  
  254.  
  255. unsigned long hsg (unsigned long value)
  256. {
  257.   unsigned char min, sec, frame;
  258.  
  259.   red_book (value, &min, &sec, &frame);
  260.   value = (unsigned long)min * 4500;
  261.   value += (short)sec * 75;
  262.   value += frame - 150;
  263.   return value;
  264. }
  265.  
  266.  
  267. unsigned long cd_head_position (void)
  268. {
  269.   struct {
  270.     unsigned char length;
  271.     unsigned char subunit;
  272.     unsigned char comcode;
  273.     unsigned short status;
  274.     char ununsed[8];
  275.     unsigned char media;
  276.     unsigned long address;
  277.     unsigned short bytes;
  278.     unsigned short sector;
  279.     unsigned long  volid;
  280.     unsigned char unused[4];
  281.   } tray_request;
  282.  
  283.   struct {
  284.     unsigned char mode;
  285.     unsigned char adr_mode;
  286.     unsigned long address;
  287.   } head_data;
  288.  
  289.   tray_request.length = sizeof (tray_request);
  290.   tray_request.subunit = 0;
  291.   tray_request.comcode = 3;
  292.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  293.   tray_request.address = (unsigned long)&head_data;
  294.   tray_request.bytes = 6;
  295.   head_data.mode = 0x01;
  296.   head_data.adr_mode = 0x00;
  297.   device_request (&tray_request);
  298.   cdrom_data.error = tray_request.status;
  299.   return head_data.address;
  300. }
  301.  
  302.  
  303. void cd_get_volume (struct volumeinfo *vol)
  304. {
  305.   struct {
  306.     unsigned char length;
  307.     unsigned char subunit;
  308.     unsigned char comcode;
  309.     unsigned short status;
  310.     char ununsed[8];
  311.     unsigned char media;
  312.     unsigned long address;
  313.     unsigned short bytes;
  314.     unsigned short sector;
  315.     unsigned long  volid;
  316.   } tray_request;
  317.  
  318.   tray_request.length = sizeof (tray_request);
  319.   tray_request.subunit = 0;
  320.   tray_request.comcode = 3;
  321.   tray_request.media = 0;
  322.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  323.   tray_request.address = (unsigned long)vol;
  324.   tray_request.bytes = 9;
  325.   vol->mode = 0x04;
  326.   device_request (&tray_request);
  327.   cdrom_data.error = tray_request.status;
  328. }
  329.  
  330.  
  331. void cd_set_volume (struct volumeinfo *vol)
  332. {
  333.   struct {
  334.     unsigned char length;
  335.     unsigned char subunit;
  336.     unsigned char comcode;
  337.     unsigned short status;
  338.     char ununsed[8];
  339.     unsigned char media;
  340.     unsigned long address;
  341.     unsigned short bytes;
  342.     unsigned char unused[4];
  343.   } cd_request;
  344.  
  345.   vol->mode = 3;
  346.   cd_request.length = sizeof (cd_request);
  347.   cd_request.subunit = 0;
  348.   cd_request.comcode = 12;
  349.   cd_request.media = 0;
  350.   cd_request.address = (unsigned long)vol;
  351.   cd_request.bytes = 9;
  352.   device_request (&cd_request);
  353.   cdrom_data.error = cd_request.status;
  354. }
  355.  
  356.  
  357. short cd_getupc (void)
  358. {
  359.   struct {
  360.     unsigned char length;
  361.     unsigned char subunit;
  362.     unsigned char comcode;
  363.     unsigned short status;
  364.     char ununsed[8];
  365.     unsigned char media;
  366.     unsigned long address;
  367.     unsigned short bytes;
  368.     unsigned short sector;
  369.     unsigned long  volid;
  370.   } tray_request;
  371.  
  372.   struct {
  373.     unsigned char mode;
  374.     unsigned char adr;
  375.     unsigned char upc[7];
  376.     unsigned char zero;
  377.     unsigned char aframe;
  378.   } upc_data;
  379.   tray_request.length = sizeof (tray_request);
  380.   tray_request.subunit = 0;
  381.   tray_request.comcode = 3;
  382.   tray_request.media = 0;
  383.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  384.   tray_request.address = (unsigned long)&upc_data;
  385.   tray_request.bytes = 11;
  386.   upc_data.mode = 0x0e;
  387.   upc_data.adr = 2;
  388.   device_request (&tray_request);
  389.   cdrom_data.error = tray_request.status;
  390.   if (upc_data.adr == 0)
  391.     memset (&upc_data.upc, 0, 7);
  392.   memcpy (&cdrom_data.upc[0], &upc_data.upc[0], 7);
  393.   return 1;
  394. }
  395.  
  396.  
  397. void cd_get_audio_info (void)
  398. {
  399.   struct {
  400.     unsigned char length;
  401.     unsigned char subunit;
  402.     unsigned char comcode;
  403.     unsigned short status;
  404.     char ununsed[8];
  405.     unsigned char media;
  406.     long address;
  407.     short bytes;
  408.     short sector;
  409.     long volid;
  410.   } ioctli;
  411.  
  412.   struct {
  413.     unsigned char mode;
  414.     unsigned char lowest;
  415.     unsigned char highest;
  416.     unsigned long address;
  417.   } track_data;
  418.  
  419.   ioctli.length = sizeof (ioctli);
  420.   ioctli.subunit = 0;
  421.   ioctli.comcode = 3;
  422.   ioctli.media = 0;
  423.   ioctli.sector = 0;
  424.   ioctli.volid = 0;
  425.   ioctli.address = (long)&track_data;
  426.   ioctli.bytes = sizeof (track_data);
  427.   track_data.mode = 0x0a;
  428.   device_request (&ioctli);
  429.   memcpy (&cdrom_data.diskid, &track_data.lowest, 6);
  430.   cdrom_data.low_audio = track_data.lowest;
  431.   cdrom_data.high_audio = track_data.highest;
  432.   red_book (track_data.address, &cdrom_data.disk_length_min, &cdrom_data.disk_length_sec, &cdrom_data.disk_length_frames);
  433.   cdrom_data.endofdisk = hsg (track_data.address);
  434.   cdrom_data.error = ioctli.status;
  435. }
  436.  
  437.  
  438. void cd_set_track (short tracknum)
  439. {
  440.   struct {
  441.     unsigned char length;
  442.     unsigned char subunit;
  443.     unsigned char comcode;
  444.     unsigned short status;
  445.     char ununsed[8];
  446.     unsigned char media;
  447.     unsigned long address;
  448.     unsigned short bytes;
  449.     unsigned short sector;
  450.     unsigned long  volid;
  451.   } tray_request;
  452.  
  453.   struct {
  454.     unsigned char mode;
  455.     unsigned char track;
  456.     unsigned long address;
  457.     unsigned char control;
  458.   } track_data;
  459.  
  460.   tray_request.length = sizeof (tray_request);
  461.   tray_request.subunit = 0;
  462.   tray_request.comcode = 3;
  463.   tray_request.media = 0;
  464.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  465.   tray_request.address = (unsigned long)&track_data;
  466.   tray_request.bytes = 7;
  467.   track_data.mode = 0x0b;
  468.   track_data.track = tracknum;
  469.   device_request (&tray_request);
  470.   cdrom_data.error = tray_request.status;
  471.   cdrom_data.track_position = hsg (track_data.address);
  472.   cdrom_data.current_track = tracknum;
  473.   cdrom_data.track_type = track_data.control & TRACK_MASK;
  474. }
  475.  
  476.  
  477. unsigned long get_track_length (short tracknum)
  478. {
  479.   unsigned long start, finish;
  480.   unsigned short ct;
  481.  
  482.   ct = cdrom_data.current_track;
  483.   cd_set_track (tracknum);
  484.   start = cdrom_data.track_position;
  485.   if (tracknum < cdrom_data.high_audio)
  486.   {
  487.     cd_set_track (tracknum+1);
  488.     finish = cdrom_data.track_position;
  489.   }
  490.   else finish = cdrom_data.endofdisk;
  491.  
  492.   cd_set_track (ct);
  493.  
  494.   finish -= start;
  495.   return finish;
  496. }
  497.  
  498.  
  499. void cd_track_length (short tracknum, unsigned char *min, unsigned char *sec, unsigned char *frame)
  500. {
  501.   unsigned long value;
  502.  
  503.   value = get_track_length (tracknum);
  504.   value += 150;
  505.   *frame = value % 75;
  506.   value -= *frame;
  507.   value /= 75;
  508.   *sec = value % 60;
  509.   value -= *sec;
  510.   value /= 60;
  511.   *min = value;
  512. }
  513.  
  514.  
  515. void cd_status (void)
  516. {
  517.   struct {
  518.     unsigned char length;
  519.     unsigned char subunit;
  520.     unsigned char comcode;
  521.     unsigned short status;
  522.     char ununsed[8];
  523.     unsigned char media;
  524.     unsigned long address;
  525.     unsigned short bytes;
  526.     unsigned short sector;
  527.     unsigned long  volid;
  528.   } tray_request;
  529.  
  530.   struct {
  531.     unsigned char mode;
  532.     unsigned long status;
  533.   } cd_data;
  534.  
  535.   tray_request.length = sizeof (tray_request);
  536.   tray_request.subunit = 0;
  537.   tray_request.comcode = 3;
  538.   tray_request.media = 0;
  539.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  540.   tray_request.address = (unsigned long)&cd_data;
  541.   tray_request.bytes = 5;
  542.  
  543.   cd_data.mode = 0x06;
  544.   device_request (&tray_request);
  545.   cdrom_data.status = cd_data.status;
  546.   cdrom_data.error = tray_request.status;
  547. }
  548.  
  549.  
  550. void cd_seek (unsigned long location)
  551. {
  552.   unsigned char min, sec, frame;
  553.   struct {
  554.     unsigned char length;
  555.     unsigned char subunit;
  556.     unsigned char comcode;
  557.     unsigned short status;
  558.     char ununsed[8];
  559.     unsigned char addressmode;
  560.     unsigned long transfer;
  561.     unsigned short sectors;
  562.     unsigned long seekpos;
  563.   } play_request;
  564.  
  565.   play_request.length = sizeof (play_request);
  566.   play_request.subunit = 0;
  567.   play_request.comcode = 131;
  568.   play_request.addressmode = 0;
  569.   play_request.transfer = 0;
  570.   play_request.sectors = 0;
  571.   play_request.seekpos = location;
  572.   device_request (&play_request);
  573.   cdrom_data.error = play_request.status;
  574. }
  575.  
  576.  
  577. void cd_play_audio (unsigned long begin, unsigned long end)
  578. {
  579.   unsigned long leng;
  580.  
  581.   struct {
  582.     unsigned char length;
  583.     unsigned char subunit;
  584.     unsigned char comcode;
  585.     unsigned short status;
  586.     char ununsed[8];
  587.     unsigned char addressmode;
  588.     unsigned long start;
  589.     unsigned long playlength;
  590.   } play_request;
  591.  
  592.   play_request.length = sizeof (play_request);
  593.   play_request.subunit = 0;
  594.   play_request.comcode = 132;
  595.   play_request.addressmode = 0;
  596.   play_request.start = begin;
  597.   play_request.playlength = end-begin;
  598.   device_request (&play_request);
  599.   cdrom_data.error = play_request.status;
  600. }
  601.  
  602.  
  603. void cd_stop_audio (void)
  604. {
  605.   struct {
  606.     unsigned char length;
  607.     unsigned char subunit;
  608.     unsigned char comcode;
  609.     unsigned short status;
  610.     char ununsed[8];
  611.   } stop_request;
  612.  
  613.   stop_request.length = sizeof (stop_request);
  614.   stop_request.subunit = 0;
  615.   stop_request.comcode = 133;
  616.   device_request (&stop_request);
  617.   cdrom_data.error = stop_request.status;
  618. }
  619.  
  620.  
  621. void cd_resume_audio (void)
  622. {
  623.   struct {
  624.     unsigned char length;
  625.     unsigned char subunit;
  626.     unsigned char comcode;
  627.     unsigned short status;
  628.     char ununsed[8];
  629.   } stop_request;
  630.  
  631.   stop_request.length = sizeof (stop_request);
  632.   stop_request.subunit = 0;
  633.   stop_request.comcode = 136;
  634.   device_request (&stop_request);
  635.   cdrom_data.error = stop_request.status;
  636. }
  637.  
  638.  
  639. void cd_cmd (unsigned char mode)
  640. {
  641.   struct {
  642.     unsigned char length;
  643.     unsigned char subunit;
  644.     unsigned char comcode;
  645.     unsigned short status;
  646.     char ununsed[8];
  647.     unsigned char media;
  648.     unsigned long address;
  649.     unsigned short bytes;
  650.     unsigned char unused[4];
  651.   } tray_request;
  652.  
  653.   unsigned char cd_mode;
  654.  
  655.   cd_mode = mode;
  656.   tray_request.length = sizeof (tray_request);
  657.   tray_request.subunit = 0;
  658.   tray_request.comcode = 12;
  659.   tray_request.media = 0;
  660.   tray_request.address = (unsigned long)&cd_mode;
  661.   tray_request.bytes = 1;
  662.   device_request (&tray_request);
  663.   cdrom_data.error = tray_request.status;
  664. }
  665.  
  666.  
  667. void cd_getpos (struct playinfo *info)
  668. {
  669.   struct {
  670.     unsigned char length;
  671.     unsigned char subunit;
  672.     unsigned char comcode;
  673.     unsigned short status;
  674.     char ununsed[8];
  675.     unsigned char media;
  676.     unsigned long address;
  677.     unsigned short bytes;
  678.     unsigned short sector;
  679.     unsigned long  volid;
  680.   } tray_request;
  681.  
  682.   tray_request.length = sizeof (tray_request);
  683.   tray_request.subunit = 0;
  684.   tray_request.comcode = 3;
  685.   tray_request.media = 0;
  686.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  687.   tray_request.address = (unsigned long)info;
  688.   tray_request.bytes = 6;
  689.   info->control = 12;
  690.   device_request (&tray_request);
  691.   cdrom_data.error = tray_request.status;
  692. }
  693.  
  694.  
  695. short cdrom_installed (void)
  696. {
  697.   inregs.h.ah = 0x15;
  698.   inregs.h.al = 0x00;
  699.   inregs.x.bx = 0;
  700.   int86 (0x2f, &inregs, &outregs);
  701.   if (outregs.x.bx == 0)
  702.     return (0);
  703.   cdrom_data.drives = outregs.x.bx;
  704.   cdrom_data.first_drive = outregs.x.cx;
  705.   cd_get_audio_info ();
  706.   return (1);
  707. }
  708.  
  709.  
  710. short cd_done_play (void)
  711. {
  712.   cd_cmd (CLOSE_TRAY);
  713.   return ((cdrom_data.error & BUSY) == 0);
  714. }
  715.  
  716.  
  717. short cd_mediach (void)
  718. {
  719.   struct {
  720.     unsigned char length;
  721.     unsigned char subunit;
  722.     unsigned char comcode;
  723.     unsigned short status;
  724.     char ununsed[8];
  725.     unsigned char media;
  726.     unsigned long address;
  727.     unsigned short bytes;
  728.     unsigned short sector;
  729.     unsigned long  volid;
  730.   } tray_request;
  731.  
  732.   struct {
  733.     unsigned char mode;
  734.     unsigned char media;
  735.   } cd_data;
  736.  
  737.   tray_request.length = sizeof (tray_request);
  738.   tray_request.subunit = 0;
  739.   tray_request.comcode = 3;
  740.   tray_request.media = 0;
  741.   tray_request.media = tray_request.sector = tray_request.volid = 0;
  742.   tray_request.address = (unsigned long)&cd_data;
  743.   tray_request.bytes = 2;
  744.  
  745.   cd_data.mode = 0x09;
  746.   device_request (&tray_request);
  747.   cdrom_data.error = tray_request.status;
  748.   return cd_data.media;
  749. }
  750.  
  751.  
  752. void cd_lock (unsigned char doormode)
  753. {
  754.   struct {
  755.     unsigned char length;
  756.     unsigned char subunit;
  757.     unsigned char comcode;
  758.     unsigned short status;
  759.     char ununsed[8];
  760.     unsigned char media;
  761.     unsigned long address;
  762.     unsigned short bytes;
  763.     unsigned char unused[4];
  764.   } tray_request;
  765.  
  766.   struct {
  767.     unsigned char mode;
  768.     unsigned char media;
  769.   } cd_data;
  770.  
  771.   tray_request.length = sizeof (tray_request);
  772.   tray_request.subunit = 0;
  773.   tray_request.comcode = 12;
  774.   tray_request.media = 0;
  775.   tray_request.address = (unsigned long)&cd_data;
  776.   tray_request.bytes = 2;
  777.   cd_data.mode = 1;
  778.   cd_data.media = doormode;
  779.   device_request (&tray_request);
  780.   cdrom_data.error = tray_request.status;
  781. }
  782.